/*
 * ACL411Midlet.java - display and interact with the Austin City Limits 2006
 * Music Festival schedule on a Java ME-capable mobile phone.
 * Copyright (C) 2006 The Blackwatch Plaid Group - http://blackwatchplaid.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.blackwatchplaid;

import java.util.*;
import java.io.InputStream;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import org.json.*;

/**
 * Displays schedule, gets notified of background downloads.
 */
public class ACL411Midlet extends MIDlet implements CommandListener, Downloader.DownloadTextJobListener {
    
    /**
     * Creates a new instance of ACL411Midlet
     */
    public ACL411Midlet() {
    }
    
    // Converts Hashtable picks:
    //      "event id => ArrayList of sources" 
    // to JSON object :
    //     source => array of event id's
    // E.g.: {"ACL246706":[1019,1025,1029,1035,1041]}
    // Why reverse the map? Mimics web requests: ask a source for their picks.
    // Should be using JSON library to do proper quoting.
    public String picksToJSON() {
        String r="{";
        for (int i=0; i<aclCodes.size(); ++i) {
            //{"ACL246706":[1019,1025,1029,1035,1041,2013,2022,2025,2040,2041,2013,2022,2025,2040,2041,3009,3026,3035,3041]}
            String aclCode = (String)aclCodes.get(i);
            r+='"'+aclCode+'"'+':'+'[';
            for (Enumeration pe=picks.keys(); pe.hasMoreElements(); ) {
                String eventID = (String)pe.nextElement();
                ArrayList pickers = (ArrayList)(picks.get(eventID));
                //System.out.println("DEBUG: picksToJSON picks.size()="+picks.size()+" eventID="+eventID+" pickers="+(pickers==null?-1:pickers.size()));
                if (pickers!=null && pickers.contains(aclCode)) {
                    r+=eventID+',';
                }
            }
            r+="]";
        }
        r+="}";
        System.out.println("DEBUG: picksToJSON: "+r);
        return r;
    }
    
    // Only set to false by Reset&Exit command so that on next restart it is
    // like a new install.
    static boolean saveOnExit = true;
    
    // Saves picks and aclCodes (sources and selected events) to record store "picks".
    public void save() {
        System.out.println("DEBUG: save: "+saveOnExit);
        if (!saveOnExit)
            return;
        // Create a record store
        RecordStore rs = null;
        RecordEnumeration renum = null;
        try {
            rs = RecordStore.openRecordStore( "picks", true );
            renum = rs.enumerateRecords(null,null,false);
            while (renum.hasNextElement()) {
                rs.deleteRecord( renum.nextRecordId() );
            }
            byte[] raw = picksToJSON().getBytes(); // had problems on S710 with UTF-8
            rs.addRecord(raw,0,raw.length);
            rs.closeRecordStore();
        } catch( RecordStoreException e ){
            // couldn't open it or create it
            System.out.println("WARN: save() failed to create 'picks': "+e);
        }
    }

    // Loads picks and aclCodes from record store "picks".
    // Sets picks to null if record store not found (ie, new install).
    // Uses will downgrade, so should prompt user whether they want to continue
    // on unexpected exceptions reading saved data. We don't want it saving
    // new empty data over good!
    public void load() {
        // Create a record store
        picks.clear();
        aclCodes.clear();
        RecordStore rs = null;
        RecordEnumeration renum = null;
        try {
            rs = RecordStore.openRecordStore( "picks", false );
            renum = rs.enumerateRecords(null,null,false);
            while (renum.hasNextElement()) {
                JSONObject r = new JSONObject(new String(renum.nextRecord()));
                for (Enumeration e = r.keys(); e.hasMoreElements(); ) {
                    String aclCode = ((String)e.nextElement()).intern();
                    aclCodes.add(aclCode);
                    JSONArray eventIDs = r.getJSONArray(aclCode);
                    for (int p=0; p<eventIDs.length(); ++p) {
                        final String eventID = eventIDs.getString(p).intern();
                        ArrayList sources = (ArrayList)picks.get(eventID);
                        if (sources==null)
                            picks.put(eventID,sources=new ArrayList(kTypicalNumSources));
                        sources.add(aclCode);
                    }
                }
                System.out.println("DEBUG: load added '"+picks.size()+"' picks from '"+aclCodes.size()+"' sources.");
            }
        } catch( RecordStoreException e ){
            // couldn't open it or create it, maybe open from resource
            System.out.println("WARN: load() did not find 'picks', maybe this is first time run.");
            picks = null;
        } catch( Exception e ){
            // couldn't open it or create it, maybe open from resource
            System.out.println("WARN: load() failed to load 'picks': "+e);
            e.printStackTrace();
            picks = null;
        } finally {
            if (rs!=null) {
                try {
                    rs.closeRecordStore();
                } catch( Exception e ){
                    // couldn't open it or create it, maybe open from resource
                    System.out.println("WARN: load() failed to closeRecordStore 'picks': "+e);
                    e.printStackTrace();
                    picks = null;
                }
            }
        }
    }
    
    final static int kBeginHour = 11;
    final static int kEndHour = 11+12;
    final static DayAndTime kBegin=new DayAndTime(Calendar.FRIDAY, kBeginHour, 00);
    final static DayAndTime kEnd=new DayAndTime(Calendar.SUNDAY, kEndHour, 00);
    
    // Download ACL schedule. It calls back into this class for progress and on completion
    private Downloader downloader = new Downloader();
    
    // All the stages, in their official order
    private ArrayList stages = new ArrayList(6);
    // The short name version of the stage
    private Hashtable stagesShortString = new Hashtable(6);
    // Which stages to display (null means all)
    private ArrayList stagesFilter = null;
    
    // The full list of events
    private ArrayList events = new ArrayList(50);
    // The events that are currently being displayed
    private ArrayList eventsShown = new ArrayList(50);
    
    // picks["2034"]=["ACL1234", "ACL9876"]
    private Hashtable picks = new Hashtable(20);
    final int kTypicalNumSources = 5;
    // aclCodes will always have at least one element. Called DEFAULT?
    private ArrayList aclCodes = new ArrayList(5);
    boolean showOnlyPicks = false;
    
    // "acl411 4.20"
    final String kBuildVersion = LocalizationSupport.getMessage("BUILD_VERSION");
    
    // Time slot to show and set cursor to in schedule list screen.
    DayAndTime selectedTimeSlot;
    {
        Date now = new Date();
        if (now.getTime()<aclTime(Calendar.FRIDAY, kBeginHour,00).getTime())
            selectedTimeSlot = new DayAndTime(kBegin.dayOfWeek,kBegin.hour,kBegin.min);
        else if (now.getTime()>aclTime(Calendar.SUNDAY, kEndHour, 00).getTime())
            selectedTimeSlot = new DayAndTime(kEnd.dayOfWeek,kEnd.hour,kEnd.min);
        else
            selectedTimeSlot = new DayAndTime(now);
    }
    // The event to select when the schedule list is displayed. Typically the
    // event found by search. Should probably save only id, since events can
    // be reloaded.
    ACLEvent selectedEvent = null;
    
    private Command exitCommand;//GEN-BEGIN:MVDFields
    private org.netbeans.microedition.lcdui.SimpleTableModel simpleTableModel1;
    private Command cmdLoadSchedule;
    private Ticker ticker1;
    private Command invalidateTableCmd;
    private List list1;
    private Command itemCommand1;
    private Command stageFilterCmd;
    private List listChooseStage;
    private Command okCommand1;
    private Image bpgMascotImg;
    private Command dumpJSONCmd;
    private Command loadScheduleFromResourceCmd;
    private Command timeCmd;
    private List listTimes;
    private Command listTimesOkCmd;
    private Command cancelCommand2;
    private Command stagesShowAllCmd;
    private Command stagesCancelCmd;
    private Command stagesUncheckAllCmd;
    private Command exitCommand1;
    private Command screenCommand1;
    private Alert helpAboutAlert;
    private Command backCommand1;
    private Command helpCommand1;
    private org.netbeans.microedition.lcdui.SplashScreen splashScreen1;
    private Command okCommand2;
    private Command scheduleSearchCmd;
    private TextBox textBoxSearch;
    private Command okCommandSearch;
    private Command cancelCommandSearch;
    private Command scheduleLoadPicksCmd;
    private TextBox textBoxACLCode;
    private Command okCommandACLCode;
    private Command cancelCommandACLCode;
    private Command timesFridayCmd;
    private Command timesSaturdayCmd;
    private Command timesSundayCmd;
    private Command timesNowCmd;
    private Command listShowOnlyPicksCmd;
    private List listPickSources;
    private Command setAsPrimaryPickCmd;
    private Command pickEventCmd;
    private Form helpAboutForm;
    private ImageItem imageItem1;
    private Command visitSiteBlackwatchPlaidCmd;
    private Command backCommand2;
    private Command donwloadUpdateCmd;
    private Command resetCmd;
    private TextField textField2;
    private StringItem stringItem1;
    private StringItem stringItem2;
    private StringItem stringItem3;//GEN-END:MVDFields
    
//GEN-LINE:MVDMethods

    // Error that is thrown when HTML parsing goes awry.
    class ParseException extends Exception {};
    
    // Throws exception if it doesn't find search string.
    public int mustFind(String html, String search, int start) throws ParseException {
        int i = html.indexOf(search, start);
        if (i==-1) {
            System.out.println("ERROR: Schedule parser could not find '"+search+"' in: "+
                    //html.substring(Math.max(0,start-10),Math.min(html.length(),start+10))+"..."+
                    //html.substring(Math.min(html.length(),Math.max(start+10,html.length()-10)))
                    html
                    );
            throw new ParseException();
        }
        return i;
    }
    
    public void notifyProgress(String url, int bytesRead, int bytesRemaining, String progress ) {
        ticker1.setString("Download progress: "+bytesRead+"/"+bytesRemaining+": "+progress);
    }
    public void notifyError(String url, int bytesRead, int bytesRemaining, String errorMessage ) {
        final String msg = "ERROR: Could not download '"+url+"'. Got '"+bytesRead+"/"+bytesRemaining+"': "+errorMessage;
        ticker1.setString(msg);
        System.out.println(msg);
    }
    // The list of events as they are being downloaded. Gets swapped into
    // main "events" when finished.
    private ArrayList tmpEvents = new ArrayList(50);
    
    public void textComplete(String url, String text ) {
        final String msg = "DEBUG: textComplete for '"+url+"' content-len="+text.length();
        ticker1.setString(msg);
        System.out.println(msg);
        int dayOfWeek = Calendar.FRIDAY;
        if (url.indexOf("day2")!=-1)
            dayOfWeek = Calendar.SATURDAY;
        else if (url.indexOf("day3")!=-1)
            dayOfWeek = Calendar.SUNDAY;
        int i = 0;
        try {
            i = mustFind(text, "<div id=\"friendschedule\"", i);
            System.out.println("DEBUG: textComplete 1 for '"+url+"': "+i);
            final String kStageHeader = "Stage:";
            i = mustFind(text, kStageHeader, i);
            System.out.println("DEBUG: textComplete 2 for '"+url+"': "+i);
            i += kStageHeader.length();
            final String kCloseTR = "</tr>";
            int finishedStages = mustFind(text, kCloseTR, i);
            System.out.println("DEBUG: textComplete 3 for '"+url+"' finishedStages="+finishedStages);
            boolean done = false;
            do {
                final String kTD = "<td>";
                i = text.indexOf(kTD, i);
                if (i==-1 || i>finishedStages) {
                    i = finishedStages;
                    break;
                }
                i += kTD.length();
                final String kCloseTD = "</td>";
                int e = mustFind(text, kCloseTD, i);
                String stage = GhettoParseHTMLUtils.trimAndCollapse(GhettoParseHTMLUtils.replaceAll(text.substring(i,e),"&amp;", "&"));
                stages.add(stage);
                i = e;
                //System.out.println("DEBUG: Adding stage '"+stage+"'");
            } while (true);
            System.out.println("DEBUG: Added '"+stages.size()+"' stages.");
            final String kCloseTable = "</table>";
            final int closeTable = mustFind(text, kCloseTable, i);
            do {
                int stageCol = 0;
                int endRow = text.indexOf(kCloseTR, i);
                if (endRow==-1 || endRow>closeTable) {
                    i = closeTable+1;
                    break;
                }
                do {
                    final String kStartEvent = "<td class=\"";
                    i = text.indexOf(kStartEvent, i);
                    if (i==-1 || i>endRow) {
                        i = endRow+1;
                        break;
                    }
                    i += kStartEvent.length();
                    if (!text.startsWith("emptyevent", i)) {
                        final String kStartEventID = "id=\"ftd";
                        i = mustFind(text, kStartEventID, i) + kStartEventID.length();
                        final String eventID = text.substring(i, mustFind(text, "\"", i));
                        System.out.println("DEBUG: Found event '"+eventID+"'");
                        final String kTime = "<span id=\"time\">";
                        i = mustFind(text, kTime, i) + kTime.length();
                        int colon = mustFind(text,":", i);
                        int hourStart = Integer.valueOf(text.substring(i, colon)).intValue();
                        int dash = mustFind(text,"-", i);
                        final int minStart = Integer.valueOf(text.substring(colon+1,dash)).intValue();
                        i = dash+1;
                        colon = mustFind(text,":", i);
                        int hourFinish = Integer.valueOf(text.substring(i, colon)).intValue();
                        int closeSpan = mustFind(text,"</span>", i);
                        final int minFinish = Integer.valueOf(text.substring(colon+1,closeSpan)).intValue();
                        if (hourStart<11)
                            hourStart += 12;
                        if (hourFinish<hourStart)
                            hourFinish += 12;
                        final String kPopWindow = "javascript:popWindow";
                        i = mustFind(text,kPopWindow,i);
                        i = mustFind(text, ">", i)+1;
                        final String name = GhettoParseHTMLUtils.trimAndCollapse(GhettoParseHTMLUtils.unescapeHTML(text.substring(i, mustFind(text, "<", i))));
//                    final String name = GhettoParseHTMLUtils.unescapeHTML(text.substring(i, mustFind(text, "<", i))).trim();
                        //!!!System.out.println("DEBUG: Added event '"+name+"'");
                        tmpEvents.add(new ACLEvent(eventID, name, aclTime(dayOfWeek,hourStart, minStart), aclTime(dayOfWeek,hourFinish, minFinish), (String)stages.get(stageCol)));
                    }
                    ++stageCol;
                } while (true);
            } while (i<closeTable);
        } catch (Exception e) {
            System.out.println("ERROR: Could not parse '"+url+"' near '"+i+"': "+e);
            
        }
        System.out.println("DEBUG: finished parsing '"+url+"'. Found events: "+tmpEvents.size());
        System.gc();
        if (url.indexOf("day3")!=-1) {
            // or redrawTable() or whatever we use to display
            list1.setTitle("Showing "+tmpEvents.size()+" events...");
            ticker1.setString("Sorting new "+tmpEvents.size()+" events...");
            // Really need to lock events during this block
            Comparator ec = new Comparator();
            tmpEvents.sort(ec);
            for (int n=0; n<tmpEvents.size(); ++n) {
                ACLEvent newEvent = (ACLEvent)tmpEvents.get(n);
                ACLEvent oldEvent = null;
                for (int o=0; o<events.size(); ++o) {
                    oldEvent = (ACLEvent)events.get(o);
                    if (oldEvent.id().equals(newEvent.id())) {
                        events.remove(oldEvent);
                        break;
                    }
                }
                if (oldEvent==null) {
                    System.out.println("INFO: Got new event: "+newEvent);
                } else if (ec.compare(oldEvent,newEvent)!=0) {
                    System.out.println("INFO: New event "+newEvent+" changed from original event "+oldEvent);
                }
            }
            for (int o=0; o<events.size(); ++o) {
                System.out.println("INFO: Old event "+events.get(o)+" was deleted.");
            }
            events.clear(); // helps gc?
            events = tmpEvents;
            tmpEvents = null; // helps gc?
            getDisplay().setCurrent(get_splashScreen1());
            list1.setTicker(null); // ticker only active while downloading
            System.out.println("Starting background thread to fillList.");
            new FillListThread().start();
            System.out.println("Changing display back to to splash screen.");
            // FillListThread sets display to list1 when finished
            //fillList(events);
        } else if (url.indexOf("day2")!=-1) {
            System.out.println("DEBUG: finished parsing '"+url+"'. Now fetching day3. Found events: "+events.size());
            downloader.getText("http://aclfestival.com/schedule/schedule_day3.aspx?loadcode=1", this);
        } else if (url.indexOf("day1")!=-1) {
            System.out.println("DEBUG: finished parsing '"+url+"'. Now fetching day2. Found events: "+events.size());
            downloader.getText("http://aclfestival.com/schedule/schedule_day2.aspx?loadcode=1", this);
        }
        
    }

    // This isn't used yet, need to rethink background stream handling. Copied 
    // from schedule parser textComplete()
    class PicksListener implements Downloader.DownloadStreamJobListener {
        public void notifyProgress(String url, int bytesRead, int bytesRemaining, String progress ) {
            ticker1.setString("Download progress: "+bytesRead+"/"+bytesRemaining+": "+progress);
        }
        public void notifyError(String url, int bytesRead, int bytesRemaining, String errorMessage ) {
            final String msg = "ERROR: Could not open stream for '"+url+"'. Got '"+bytesRead+"/"+bytesRemaining+"': "+errorMessage;
            ticker1.setString(msg);
            System.out.println(msg);
        }
        public void streamOpened(String url, InputStream is ) {
            final String msg = "DEBUG: PicksListener.streamOpened for '"+url+"'.";
            //!!!ticker1.setString(msg);
            System.out.println(msg);
            int dayOfWeek = Calendar.FRIDAY;
            if (url.indexOf("day2")!=-1)
                dayOfWeek = Calendar.SATURDAY;
            else if (url.indexOf("day3")!=-1)
                dayOfWeek = Calendar.SUNDAY;
            int i = 0;
            if (true)
                return;
            String text = null;
            try {
                i = mustFind(text, "<div id=\"friendschedule\"", i);
                System.out.println("DEBUG: textComplete 1 for '"+url+"': "+i);
                final String kStageHeader = "Stage:";
                i = mustFind(text, kStageHeader, i);
                System.out.println("DEBUG: textComplete 2 for '"+url+"': "+i);
                i += kStageHeader.length();
                final String kCloseTR = "</tr>";
                int finishedStages = mustFind(text, kCloseTR, i);
                System.out.println("DEBUG: textComplete 3 for '"+url+"' finishedStages="+finishedStages);
                boolean done = false;
                do {
                    final String kTD = "<td>";
                    i = text.indexOf(kTD, i);
                    if (i==-1 || i>finishedStages) {
                        i = finishedStages;
                        break;
                    }
                    i += kTD.length();
                    final String kCloseTD = "</td>";
                    int e = mustFind(text, kCloseTD, i);
                    String stage = GhettoParseHTMLUtils.trimAndCollapse(GhettoParseHTMLUtils.replaceAll(text.substring(i,e),"&amp;", "&"));
                    stages.add(stage);
                    i = e;
                    //System.out.println("DEBUG: Adding stage '"+stage+"'");
                } while (true);
                System.out.println("DEBUG: Added '"+stages.size()+"' stages.");
                final String kCloseTable = "</table>";
                final int closeTable = mustFind(text, kCloseTable, i);
                do {
                    int stageCol = 0;
                    int endRow = text.indexOf(kCloseTR, i);
                    if (endRow==-1 || endRow>closeTable) {
                        i = closeTable+1;
                        break;
                    }
                    do {
                        final String kStartEvent = "<td class=\"";
                        i = text.indexOf(kStartEvent, i);
                        if (i==-1 || i>endRow) {
                            i = endRow+1;
                            break;
                        }
                        i += kStartEvent.length();
                        if (!text.startsWith("emptyevent", i)) {
                            final String kStartEventID = "id=\"ftd";
                            i = mustFind(text, kStartEventID, i) + kStartEventID.length();
                            final String eventID = text.substring(i, mustFind(text, "\"", i));
                            System.out.println("DEBUG: Found event '"+eventID+"'");
                            final String kTime = "<span id=\"time\">";
                            i = mustFind(text, kTime, i) + kTime.length();
                            int colon = mustFind(text,":", i);
                            int hourStart = Integer.valueOf(text.substring(i, colon)).intValue();
                            int dash = mustFind(text,"-", i);
                            final int minStart = Integer.valueOf(text.substring(colon+1,dash)).intValue();
                            i = dash+1;
                            colon = mustFind(text,":", i);
                            int hourFinish = Integer.valueOf(text.substring(i, colon)).intValue();
                            int closeSpan = mustFind(text,"</span>", i);
                            final int minFinish = Integer.valueOf(text.substring(colon+1,closeSpan)).intValue();
                            if (hourStart<11)
                                hourStart += 12;
                            if (hourFinish<hourStart)
                                hourFinish += 12;
                            final String kPopWindow = "javascript:popWindow";
                            i = mustFind(text,kPopWindow,i);
                            i = mustFind(text, ">", i)+1;
                            final String name = GhettoParseHTMLUtils.trimAndCollapse(GhettoParseHTMLUtils.unescapeHTML(text.substring(i, mustFind(text, "<", i))));
//                    final String name = GhettoParseHTMLUtils.unescapeHTML(text.substring(i, mustFind(text, "<", i))).trim();
                            System.out.println("DEBUG: Added event '"+name+"'");
                            events.add(new ACLEvent(eventID, name, aclTime(dayOfWeek,hourStart, minStart), aclTime(dayOfWeek,hourFinish, minFinish), (String)stages.get(stageCol)));
                        }
                        ++stageCol;
                    } while (true);
                } while (i<closeTable);
            } catch (Exception e) {
                System.out.println("ERROR: Could not parse '"+url+"' near '"+i+"': "+e);
                
            }
            System.out.println("DEBUG: finished parsing '"+url+"'. Found events: "+events.size());
            System.gc();
            //!!!redrawTable();
            list1.setTitle("Showing "+events.size()+" events...");
            fillList(events);
        }
        
        
    }
    PicksListener picksListener = new PicksListener();

    // Compare two ACL Events for sorting.
    // Sorts events by start time, then stage, then name
    class Comparator implements ArrayList.Comparator {
        public int compare(Object o1, Object o2) {
            ACLEvent e1=(ACLEvent)o1;
            ACLEvent e2=(ACLEvent)o2;
            long st1 = e1.start().getTime();
            long st2 = e2.start().getTime();
            // This sucks, I am writing time out as a (double)(getTime()/1000)
            // to avoid long, but that means times are no longer exact to second.
            final int kFUDGE = 1000*60*2; // within a minute should be considered the same time
            if (st1-st2>kFUDGE) return 1;
            if (st2-st1>kFUDGE) return -1;
            int so1 = stages.indexOf(e1.stage());
            int so2 = stages.indexOf(e2.stage());
            if (so1<so2) return -1;
            if (so2>so1) return 1;
            return e1.name().compareTo(e2.name());
        }
        
        public boolean equals(Object o1, Object o2) {
            return compare(o1,o2)==0;
        }
        
    }

    // Returns event corresponding to line current selected (time/stage or name).
    // Can optionally toggle it as a pick (changes just that one line, no redraw).
    public ACLEvent getSelectedEvent(boolean togglePick) {
//        eventsShown.clear();
        //System.out.println("DEBUG: getSelectedEvent: list1.size()="+list1.size()+" list1.getSelectedIndex()="+list1.getSelectedIndex());
        
        int sel = list1.getSelectedIndex();
        Date minSlot = aclTime(showOnlyPicks?Calendar.FRIDAY:selectedTimeSlot.dayOfWeek, 00, 01);
//        Date maxSlot = aclTime(showOnlyPicks?Calendar.SUNDAY:selectedTimeSlot.dayOfWeek, 23, 59);
//        for (int i=0; i<events.size(); ++i) {
//            ACLEvent e = (ACLEvent)events.get(i);
//            if (e.start().getTime()>=minSlot.getTime()
//            && e.start().getTime()<=maxSlot.getTime()
//            && (stagesFilter==null || stagesFilter.contains(e.stage()))
//            && (!showOnlyPicks || picks.get(e.id())!=null)) {
//                eventsShown.add(e);
//                //System.out.println("DEBUG: fillList will show event '"+e+"'");
//            } else {
//                //System.out.println("DEBUG: fillList ignoring event '"+e+"'");
//            }
//        }
        //!System.out.println("DEBUG: fillList showing '"+eventsShown.size()+"' events.");
        //!eventsShown.sort(new Comparator());
        //!list1.deleteAll();
        //!System.gc();
        //!Date now = aclTime(selectedTimeSlot.dayOfWeek, selectedTimeSlot.hour, selectedTimeSlot.min);
        // show "---FRIDAY---" separator in list if showing all days
        int lastDay = showOnlyPicks?-1:new DayAndTime(minSlot).dayOfWeek;
        boolean alreadySetSelected = false;
        for (int i=0; i<eventsShown.size(); ++i) {
            ACLEvent e = (ACLEvent)eventsShown.get(i);
            final DayAndTime start = new DayAndTime(e.start());
            final DayAndTime finish = new DayAndTime(e.finish());
            if (start.dayOfWeek!=lastDay) {
//                list1.append("-----"+start.dayOfWeekStr()+"-----", null);
                if (sel--==0)
                    return null; // selecting a weekday name makes no sense
                lastDay = start.dayOfWeek;
            }
//            final String dur = start.asTimeShortString( ) +" -" + finish.asTimeShortString()
//                + " @ " + stagesShortString.get(e.stage());
//            list1.append(dur, null);
            if (sel<2) {
                
                if (togglePick) {
                    ArrayList sources = (ArrayList)picks.get(e.id());
                    final int eventNameLine = list1.getSelectedIndex()+(sel==0?1:0);
                    //System.out.println("DEBUG: "eventNameLine="+eventNameLine+" list1.size()="+list1.size()+" list1.getSelectedIndex()="+list1.getSelectedIndex()+": "+e.name());
                    if (sources!=null && sources.contains(aclCodes.get(0))) {
                        // sel will be one if the time/stage line was selected
                        list1.set(eventNameLine, " "+list1.getString(eventNameLine).substring(1),null);
                        sources.remove(aclCodes.get(0));
                        //System.out.println("DEBUG: unpicked event: "+e.name());
                    } else { // need to add it
                        if (sources==null)
                            picks.put(e.id(),sources=new ArrayList(kTypicalNumSources));
                        list1.set(eventNameLine, "*"+list1.getString(eventNameLine).substring(1),null);
                        sources.add(aclCodes.get(0));
                        //System.out.println("DEBUG: picked event: "+e.name());
                    }
                }
                return e; // they selected the event (the date/stage line, but ignoring that for now)
            }
            sel-=2;
            
//            int minTilStarts = (int)((e.start().getTime()-now.getTime())/1000/60);
//            int minTilFinished = (int)((e.finish().getTime()-now.getTime())/1000/60);
//            final int kTimeAlert = 15;
//            char prefix;
//            if (minTilStarts>0 && minTilStarts<=kTimeAlert)
//                prefix = '^'; // about to start
//            else if (minTilStarts<=0 && minTilFinished>kTimeAlert)
//                prefix = '='; // we're in the middle of it
//            else if (minTilStarts<=0 && minTilFinished>=0)
//                prefix = '#'; // it's closing up
//            else
//                prefix = ' ';
//            boolean picked = picks.get(e.id())!=null;
//            list1.append(""+(picked?'*':' ')+' '+prefix+' '+e.name(), null);
//            if (!alreadySetSelected && minTilStarts>=0) {
//                System.out.println("DEBUG: setting list selection based on "+(new DayAndTime(now)).asShortString());
//                list1.setSelectedIndex(list1.size()-2, true);
//                alreadySetSelected = true;
//            }
            //System.out.println("DEBUG: fillList adding list item: "+dur+" - "+e.name());
            
            /* buggy and fonts don't work on S710!!!
            if (e.start().getTime()>=now.getTime() && now.getTime()<=e.finish().getTime()) {
                list1.setFont(list1.size()-2, Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_UNDERLINED,Font.SIZE_MEDIUM));
                list1.setFont(list1.size()-1, Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE));
            } else {
                list1.setFont(list1.size()-2, Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_SMALL));
                list1.setFont(list1.size()-1, Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM));
            }
             */
        }
//        if (!alreadySetSelected && list1.size()>0) {
//            System.out.println("DEBUG: setting selection to last item since no slot matching "+(new DayAndTime(now)).asShortString());
//            list1.setSelectedIndex(list1.size()-2, true);
//            alreadySetSelected = true;
//        }
        System.out.println("ERROR: getSelectedEvent did not find sel/events/list: "+sel+"/"+eventsShown.size()+"/"+list1.size());
        return null;
    }
    

    // Filters the events based on selectedTimeSlot, showOnlyPicks, stagesFilter.
    // Sets selection based on selectedTimeSlot and selectedEvent.
    // Fills eventsShown, in same order as displayed in list.
    public void fillList(ArrayList events) {
        eventsShown.clear();
        Date minSlot = aclTime(showOnlyPicks?Calendar.FRIDAY:selectedTimeSlot.dayOfWeek, 00, 01);
        Date maxSlot = aclTime(showOnlyPicks?Calendar.SUNDAY:selectedTimeSlot.dayOfWeek, 23, 59);
        for (int i=0; i<events.size(); ++i) {
            ACLEvent e = (ACLEvent)events.get(i);
            if (e.start().getTime()>=minSlot.getTime()
            && e.start().getTime()<=maxSlot.getTime()
            && (stagesFilter==null || stagesFilter.contains(e.stage()))
            && (!showOnlyPicks || (picks.get(e.id())!=null && ((ArrayList)picks.get(e.id())).size()>0)) ) {
                eventsShown.add(e);
                //System.out.println("DEBUG: fillList will show event '"+e+"'");
            } else {
                //System.out.println("DEBUG: fillList ignoring event '"+e+"'");
            }
        }
        System.out.println("DEBUG: fillList showing '"+eventsShown.size()+"' events.");
        eventsShown.sort(new Comparator());
        list1.deleteAll();
        System.gc();
        Date now = aclTime(selectedTimeSlot.dayOfWeek, selectedTimeSlot.hour, selectedTimeSlot.min);
        // show "---FRIDAY---" separator in list if showing all days
        int lastDay = showOnlyPicks?-1:new DayAndTime(minSlot).dayOfWeek;
        boolean alreadySetSelected = false;
        for (int i=0; i<eventsShown.size(); ++i) {
            ACLEvent e = (ACLEvent)eventsShown.get(i);
            final DayAndTime start = new DayAndTime(e.start());
            final DayAndTime finish = new DayAndTime(e.finish());
            if (start.dayOfWeek!=lastDay) {
                list1.append("-----"+start.dayOfWeekStr()+"-----", null);
                lastDay = start.dayOfWeek;
            }
            final String dur = start.asTimeShortString( ) +" -" + finish.asTimeShortString()
            + " @ " + stagesShortString.get(e.stage());
            list1.append(dur, null);
            int minTilStarts = (int)((e.start().getTime()-now.getTime())/1000/60);
            int minTilFinished = (int)((e.finish().getTime()-now.getTime())/1000/60);
            final int kTimeAlert = 15;
            char prefix;
            if (minTilStarts>0 && minTilStarts<=kTimeAlert)
                prefix = '^'; // about to start
            else if (minTilStarts<=0 && minTilFinished>kTimeAlert)
                prefix = '='; // we're in the middle of it
            else if (minTilStarts<=0 && minTilFinished>=0)
                prefix = '#'; // it's closing up
            else
                prefix = ' ';
            ArrayList sources = (ArrayList)picks.get(e.id());
            boolean picked = sources!=null && sources.contains(aclCodes.get(0));
            list1.append(""+(picked?'*':' ')+' '+prefix+' '+e.name(), null);
            if (!alreadySetSelected) {
                if (selectedEvent==null) {
                    if (minTilStarts>=0) {
                        System.out.println("DEBUG: setting list selection based on "+(new DayAndTime(now)).asShortString());
                        list1.setSelectedIndex(list1.size()-2, true);
                        alreadySetSelected = true;
                    }
                } else if (e==selectedEvent || e.start().getTime()>selectedEvent.start().getTime()) {
                    System.out.println("DEBUG: setting list selection based on "+(new DayAndTime(now)).asShortString()+" and event: "+selectedEvent);
                    list1.setSelectedIndex(list1.size()-1, true);
                    alreadySetSelected = true;
                }
            }
            //System.out.println("DEBUG: fillList adding list item: "+dur+" - "+e.name());
            
            /* buggy and fonts don't work on S710!!!
            if (e.start().getTime()>=now.getTime() && now.getTime()<=e.finish().getTime()) {
                list1.setFont(list1.size()-2, Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_UNDERLINED,Font.SIZE_MEDIUM));
                list1.setFont(list1.size()-1, Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE));
            } else {
                list1.setFont(list1.size()-2, Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_SMALL));
                list1.setFont(list1.size()-1, Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM));
            }
             */
        }
        if (!alreadySetSelected && list1.size()>0) {
            System.out.println("DEBUG: setting selection to last item since no slot matching "+(new DayAndTime(now)).asShortString());
            list1.setSelectedIndex(list1.size()-2, true);
            alreadySetSelected = true;
        }
        
        list1.setTitle(clockStr()+(showOnlyPicks?" * ":" | ")+selectedTimeSlot.asShortString().toUpperCase());
        System.gc();
    }

    // Load sources and their chosen events from resource file.
    public void loadPicksFromResource() {
        String scheduleJSON=null;
        InputStream is = null;
        
        picks.clear();
        scheduleJSON=null;
        is = null;
        try {
            Class clazz = /*Runtime.getRuntime().*/getClass();
            is = clazz.getResourceAsStream("acl2006data_picks.json");
            byte[] raw = new byte[8192];
            int lastRead, length = 0;
            while ((lastRead=is.read(raw, length, raw.length-length)) != -1) {
                length += lastRead;
            }
            JSONObject r = new JSONObject(scheduleJSON=new String(raw,0,length,"ISO-8859-1"));
            for (Enumeration e = r.keys(); e.hasMoreElements(); ) {
                String aclCode = ((String)e.nextElement()).intern();
                aclCodes.add(aclCode);
                JSONArray eventIDs = r.getJSONArray(aclCode);
                for (int p=0; p<eventIDs.length(); ++p) {
                    final String eventID = eventIDs.getString(p);
                    ArrayList sources = (ArrayList)picks.get(eventID);
                    if (sources==null)
                        picks.put(eventID,sources=new ArrayList(kTypicalNumSources));
                    sources.add(aclCode);
                }
            }
            System.out.println("DEBUG: loadScheduleFromResource added '"+picks.size()+"' picks.");
        } catch (Exception e) {
            System.out.println("ERROR: loadScheduleFromResource error parsing picks: "+e+" for: "+scheduleJSON);
            e.printStackTrace();
        } finally {
            if (is!=null) {
                try {
                    is.close();
                } catch (Exception ei) {
                    System.out.println("ERROR: loadScheduleFromResource error closing stream when parsing events: "+ei+" for: "+scheduleJSON);
                    ei.printStackTrace();
                }
            }
        }
        
    }

    // 
    public void loadScheduleFromResource() {
        events.clear();
        stages.clear();
        String scheduleJSON=null;
        InputStream is = null;
        try {
            Class clazz = /*Runtime.getRuntime().*/getClass();
            is = clazz.getResourceAsStream("acl2006data.json");
            byte[] raw = new byte[20000]; //!!! need to stream JSON
            int lastRead, length = 0;
            while (raw.length>length && (lastRead=is.read(raw, length, raw.length-length)) != -1) {
                length += lastRead;
            }
            if (raw.length<=length)
                System.out.println("ERROR: loadScheduleFromResource didn't expect such a big resource.");
            JSONArray r = new JSONArray(scheduleJSON=new String(raw,0,length,"ISO-8859-1"));
            for (int i=0; i<r.length(); ++i) {
                ACLEvent e = new ACLEvent(r.getJSONObject(i));
                //!!!System.out.println("DEBUG: adding event "+e);
                events.add(e);
            }
            events.sort(new Comparator());
            System.out.println("DEBUG: loadScheduleFromResource added '"+events.size()+"' events.");
            System.out.println("DEBUG: loadScheduleFromResource last event is "+events.get(events.size()-1));
            
        } catch (Exception e) {
            System.out.println("ERROR: loadScheduleFromResource error parsing events: "+e+" for: "+scheduleJSON);
            e.printStackTrace();
        } finally {
            if (is!=null) {
                try {
                    is.close();
                } catch (Exception ei) {
                    System.out.println("ERROR: error closing stream when parsing events: "+ei+" for: "+scheduleJSON);
                    ei.printStackTrace();
                }
            }
        }
        scheduleJSON=null;
        is = null;
        try {
            Class clazz = /*Runtime.getRuntime().*/getClass();
            is = clazz.getResourceAsStream("acl2006data_stages.json");
            byte[] raw = new byte[8192];
            int lastRead, length = 0;
            while ((lastRead=is.read(raw, length, raw.length-length)) != -1) {
                length += lastRead;
            }
            JSONArray r = new JSONArray(scheduleJSON=new String(raw,0,length,"ISO-8859-1"));
            for (int i=0; i<r.length(); ++i) {
                JSONObject stage_stg = r.getJSONObject(i);
                String stage = (String)stage_stg.keys().nextElement();
                stages.add(stage);
                stagesShortString.put(stage,stage_stg.getString(stage));
                //System.out.println("DEBUG: adding stage: "+stage+"/"+stage_stg.getString(stage));
            }
            System.out.println("DEBUG: loadScheduleFromResource added '"+stages.size()+"' stages.");
        } catch (Exception e) {
            System.out.println("ERROR: loadScheduleFromResource error parsing events: "+e+" for: "+scheduleJSON);
            e.printStackTrace();
        } finally {
            if (is!=null) {
                try {
                    is.close();
                } catch (Exception ei) {
                    System.out.println("ERROR: loadScheduleFromResource error closing stream when parsing events: "+ei+" for: "+scheduleJSON);
                    ei.printStackTrace();
                }
            }
        }
    }

    // Table was not working on S710 -- custom items don't get traversal events
    // or something. Table view option would be nice, or maybe tabs, but list
    // seems fine for now.
    public void redrawTable() {
        if (stages.size()==0)
            return;
            /*
            ACLEvent[] events = {
                new ACLEvent("1025", "Gnarls Barkley", aclTime(Calendar.FRIDAY, 16, 30), aclTime(Calendar.FRIDAY, 17, 30), "AT&T"),
                new ACLEvent("1029", "Cat Power & The Memphis Rhythm Band", aclTime(Calendar.FRIDAY, 17, 30), aclTime(Calendar.FRIDAY, 18, 30), "AT&T blue room"),
                new ACLEvent("1035", "Thievery Corporation", aclTime(Calendar.FRIDAY, 18, 30), aclTime(Calendar.FRIDAY, 19, 30), "AT&T blue room"),
            };
             */
        Date minSlot = aclTime(Calendar.FRIDAY, 23, 59);
        Date maxSlot = aclTime(Calendar.FRIDAY, 00, 00);
        Hashtable stagesMap = new Hashtable();
        //Hashtable friends = new Hashtable();
        for (int i=0; i<events.size(); ++i) {
            ACLEvent event = (ACLEvent)events.get(i);
            if (event.start().getTime()<minSlot.getTime()) {
                minSlot = event.start();
            }
            if (event.finish().getTime()>maxSlot.getTime())
                maxSlot = event.finish();
            Vector actList = (Vector)stagesMap.get(event.stage());
            if (actList==null) {
                actList = new Vector();
                stagesMap.put(event.stage(), actList);
            }
            actList.addElement(event);
            //for (Enumeration ef = events[i].links)
        }
        Calendar cal = Calendar.getInstance(/*!!!TimeZone.getTimeZone("CDT")*/);
        cal.setTime(minSlot);
        if (cal.get(Calendar.MINUTE)<30)
            cal.set(Calendar.MINUTE, 0);
        else if (cal.get(Calendar.MINUTE)>30)
            cal.set(Calendar.MINUTE, 30);
        minSlot = cal.getTime();
        int numHalfHourBlocks = (int)((maxSlot.getTime()-minSlot.getTime())/1000/60/30);
        String[][] values = new String[numHalfHourBlocks][stagesMap.size()];
        String[] stagesHeaders = new String[stagesMap.size()];
        Enumeration es = stagesMap.keys();
        int si=0;
        final int MAX_NAME_DISPLAY = 15;
        while (es.hasMoreElements()) {
            String stageName = (String)es.nextElement();
            stagesHeaders[si++] = stageName.length()>MAX_NAME_DISPLAY?stageName.substring(0,MAX_NAME_DISPLAY):stageName;
        }
        
            /*!!!
            int timeRow = (int)((maxSlot.getTime()-minSlot.getTime())/1000/60/30);
            cal = Calendar.getInstance(TimeZone.getTimeZone("CDT"));
            cal.setTime(maxSlot);
            System.out.println("DEBUG: timeRow/numHalfHourBlocks"+timeRow+"/"+numHalfHourBlocks+". maxSlot="+cal.get(Calendar.HOUR_OF_DAY)+". timeRow=");
            values[timeRow-1][0] = "__Last="+cal.get(Calendar.HOUR_OF_DAY);
             */
        
        int stageCol = 0;
        for (int i=0; i<stages.size(); ++i) {
            Vector actList = (Vector)stagesMap.get(stages.get(i));
            if (actList!=null) {
                for (int ai=0; ai<actList.size(); ++ai) {
                    ACLEvent e = (ACLEvent)actList.elementAt(ai);
                    int timeRow = (int)((e.start().getTime()-minSlot.getTime())/1000/60/30);
                    if (timeRow+1>=values.length) {
                        System.out.println("ERROR: redrawTable: "+e.toString());
                    }
                    values[timeRow+1][stageCol] = e.name().length()>MAX_NAME_DISPLAY?e.name().substring(0,MAX_NAME_DISPLAY):e.name();
                    /*Calendar*/ cal = Calendar.getInstance(TimeZone.getTimeZone("CDT"));
                    cal.setTime(e.start());
                    String dur = (cal.get(Calendar.HOUR)==0?12:cal.get(Calendar.HOUR))+":"+(cal.get(Calendar.MINUTE)<10?"0":"")+cal.get(Calendar.MINUTE)+(cal.get(Calendar.AM_PM)==Calendar.AM?"AM":"PM")+"-";
                    cal = Calendar.getInstance(TimeZone.getTimeZone("CDT"));
                    cal.setTime(e.finish());
                    dur += (cal.get(Calendar.HOUR)==0?12:cal.get(Calendar.HOUR))+":"+(cal.get(Calendar.MINUTE)<10?"0":"")+cal.get(Calendar.MINUTE)+(cal.get(Calendar.AM_PM)==Calendar.AM?"AM":"PM");
                    dur += "_" + e.stage();
                    values[timeRow][stageCol] = dur;
                }
                ++stageCol;
            }
        }
        //simpleTableModel1.setColumnNames(stagesHeaders);
        //simpleTableModel1.setValues(values);
        //simpleTableModel1.fireTableModelChanged();
        ticker1.setString("redrawTable Found "+events.size()+".");
    }

    // Returns current time, as DayAndTime.asShortString()
    static public String clockStr() {
        //TimeZone cdt = TimeZone.getDefault();
        /* timezone support sucks
        System.out.println("!!!DEBUG: TimeZone.getDefault()="+cdt.getID()+" rawoffset="+(cdt.getRawOffset()/1000/60/60)+" SepOffest="+(cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60)+" DST="+cdt.useDaylightTime());
        System.out.println("DEBUG: TimeZone.getTimeZone(DEFAULT)="+TimeZone.getTimeZone("DEFAULT").getID());
        System.out.println("DEBUG: TimeZone.getTimeZone(CST)="+TimeZone.getTimeZone("CST").getID());
        System.out.println("DEBUG: TimeZone.getTimeZone(CDT)="+TimeZone.getTimeZone("CDT").getID());
        System.out.println("DEBUG: TimeZone.getTimeZone(America/Chicago)="+TimeZone.getTimeZone("America/Chicago").getID());
        System.out.println("DEBUG: TimeZone.getAvailableIDs().length="+TimeZone.getAvailableIDs().length);
        System.out.println("DEBUG: new Date()="+new Date());
         */
        
        //Calendar nowc = Calendar.getInstance();
        //Calendar nowc787 = Calendar.getInstance(AustinTimeZone2006.getInstance());
        DayAndTime d = new DayAndTime(/*nowc.getTime()*/new Date());
        //System.out.println("!!!DEBUG: it is now: "+d.asShortString()+" or "+nowc.get(Calendar.DAY_OF_WEEK)+"-"+nowc.get(Calendar.HOUR_OF_DAY)+nowc787.get(Calendar.DAY_OF_WEEK)+"-"+nowc787.get(Calendar.HOUR_OF_DAY));
        return d.asShortString();
    }
    
    // Task to update schedule list title so it constantly shows correct time.
    private static Timer clockTimer = new Timer();
    class ClockUpdateTask extends TimerTask {
        public void run() {
            list1.setTitle(clockStr()+(showOnlyPicks?" * ":" | ")+selectedTimeSlot.asShortString().toUpperCase());
        }
    }
    /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin
     */
    private void initialize() {//GEN-END:MVDInitBegin
        // Insert pre-init code here
        // Don't initialize again, this gets called when coming out of Pause
        if (events.size()>0) {
            return;
        }
        getDisplay().setCurrent(get_splashScreen1());//GEN-LINE:MVDInitInit
        // Insert post-init code here
        list1.setTitle("Loading events... "+clockStr());
        loadScheduleFromResource();
        load(); // overwrite picks, need to use resource as fallback
        if (picks==null) {
            System.out.println("ERROR: initialize could not load saved picks. Loading from resource.");
            picks = new Hashtable();
            loadPicksFromResource();
        }
        if (aclCodes.size()==0) {
            aclCodes.add("DEFAULT");
        }
        fillList(events);
        getDisplay().setCurrent(list1);
        clockTimer.schedule(new ClockUpdateTask(),60*1000,60*1000);
    }//GEN-LINE:MVDInitEnd

    // Launch this thread while displaying a splash screen.
    // Should probably look into NetBeans' WaitScreen / tasks.
    class FillListThread extends Thread {
        FillListThread() {
            super("FillListThread");
        }
        public void run() {
            fillList(events);
            getDisplay().setCurrent(list1);
        }
    }
    
    /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin
     * @param command the Command that ws invoked
     * @param displayable the Displayable on which the command was invoked
     */
    public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin
        // Insert global pre-action code here
        try {
            if (displayable == list1) {
                ACLEvent e = getSelectedEvent(false);
                if (e!=null) {
                    selectedTimeSlot = new DayAndTime(e.start());
                    selectedEvent = e;
                }
            }
            if (displayable == list1) {//GEN-BEGIN:MVDCABody
                if (command == stageFilterCmd) {//GEN-END:MVDCABody
                // Insert pre-action code here
                    getDisplay().setCurrent(get_listChooseStage());//GEN-LINE:MVDCAAction33
                // Insert post-action code here
                listChooseStage.setTitle(LocalizationSupport.getMessage("Select_Stages_to_Display"));
                listChooseStage.deleteAll();
                for (int i=0; i<stages.size(); ++i) {
                    listChooseStage.append((String)stages.get(i),null);
                    listChooseStage.setSelectedIndex(i,stagesFilter==null||stagesFilter.contains(stages.get(i)));
                }
                } else if (command == dumpJSONCmd) {//GEN-LINE:MVDCACase33
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction46
                // Insert post-action code here
                JSONArray r = new JSONArray();
                for (int i=0; i<events.size(); ++i) {
                    ACLEvent e = (ACLEvent)events.get(i);
                    r.put(e.toJSON());
                }
                System.out.println("============JSON=============");
                System.out.println(r.toString());
                System.out.println("============JSON=============");
                } else if (command == loadScheduleFromResourceCmd) {//GEN-LINE:MVDCACase46
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction48
                // Insert post-action code here
                loadScheduleFromResource();
                
                } else if (command == timeCmd) {//GEN-LINE:MVDCACase48
                // Insert pre-action code here
                get_listTimes();
                if (selectedTimeSlot.dayOfWeek==Calendar.FRIDAY)
                    listTimes.removeCommand(get_timesFridayCmd());
                else
                    listTimes.addCommand(get_timesFridayCmd());
                if (selectedTimeSlot.dayOfWeek==Calendar.SATURDAY)
                    listTimes.removeCommand(get_timesSaturdayCmd());
                else
                    listTimes.addCommand(get_timesSaturdayCmd());
                if (selectedTimeSlot.dayOfWeek==Calendar.SUNDAY)
                    listTimes.removeCommand(get_timesSundayCmd());
                else
                    listTimes.addCommand(get_timesSundayCmd());
                int i=0;
                for (DayAndTime slot=kBegin.clone(); slot.compareTo(kEnd, Calendar.FRIDAY)<=0; slot.incHour(kBeginHour,kEndHour)) {
                    if (this.selectedTimeSlot.compareTo(slot, Calendar.FRIDAY)<=0) {
                        listTimes.setSelectedIndex(i, true);
                        break;
                    }
                    ++i;
                }
                getDisplay().setCurrent(get_listTimes());//GEN-LINE:MVDCAAction50
                // Insert post-action code here
                } else if (command == exitCommand1) {//GEN-LINE:MVDCACase50
                // Insert pre-action code here
                    exitMIDlet();//GEN-LINE:MVDCAAction96
                // Insert post-action code here
                } else if (command == helpCommand1) {//GEN-LINE:MVDCACase96
                // Insert pre-action code here
                    getDisplay().setCurrent(get_helpAboutForm());//GEN-LINE:MVDCAAction106
                // Insert post-action code here
                } else if (command == scheduleSearchCmd) {//GEN-LINE:MVDCACase106
                // Insert pre-action code here
                    getDisplay().setCurrent(get_textBoxSearch());//GEN-LINE:MVDCAAction113
                // Insert post-action code here
                } else if (command == scheduleLoadPicksCmd) {//GEN-LINE:MVDCACase113
                // Insert pre-action code here
                    getDisplay().setCurrent(get_textBoxACLCode());//GEN-LINE:MVDCAAction120
                // Insert post-action code here
                } else if (command == listShowOnlyPicksCmd) {//GEN-LINE:MVDCACase120
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction137
                // Insert post-action code here
                showOnlyPicks = !showOnlyPicks;
                list1.removeCommand(listShowOnlyPicksCmd);
                listShowOnlyPicksCmd = new Command(showOnlyPicks?"Show All":"Only Picks", Command.SCREEN, 4);
                list1.addCommand(listShowOnlyPicksCmd);
                
                getDisplay().setCurrent(get_splashScreen1());
                
                System.out.println("Starting background thread to fillList.");
                new FillListThread().start();
                System.out.println("Changing display back to to splash screen.");
                // FillListThread sets display to list1 when finished
                } else if (command == pickEventCmd) {//GEN-LINE:MVDCACase137
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction143
                // Insert post-action code here
                // Find selected event and toggle its pick status
                ACLEvent e = getSelectedEvent(true);
                if (e==null) {
                    System.out.println("DEBUG: pickEventCmd displaying error.");
                    getDisplay().setCurrent(new Alert("Invalid Pick","The selected item is not selectable as a pick.", null, AlertType.ERROR), list1);
                }
                } else if (command == cmdLoadSchedule) {//GEN-LINE:MVDCACase143
                    // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction167
                    // Insert post-action code here
                    list1.setTicker(get_ticker1());
                    downloader.getText("http://aclfestival.com/schedule/schedule_day1.aspx?loadcode=1", this);                    
                    // textComplete() will fetch other days and redisplay schedule when done
                }//GEN-BEGIN:MVDCACase167
            } else if (displayable == listChooseStage) {
                if (command == okCommand1) {//GEN-END:MVDCACase167
                // Insert pre-action code here
                if (stagesFilter==null)
                    stagesFilter = new ArrayList(stages.size());
                else
                    stagesFilter.clear();
                boolean[] selected = new boolean[listChooseStage.size()];
                listChooseStage.getSelectedFlags(selected);
                for (int i=0; i<selected.length; ++i) {
                    if (selected[i])
                        stagesFilter.add(stages.get(i));
                }
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction37
                // Insert post-action code here
                } else if (command == stagesShowAllCmd) {//GEN-LINE:MVDCACase37
                // Insert pre-action code here
                if (stagesFilter==null)
                    stagesFilter = new ArrayList(stages.size());
                else
                    stagesFilter.clear();
                for (int i=0; i<stages.size(); ++i) {
                    stagesFilter.add(stages.get(i));
                }
                listChooseStage.setTitle("Showing all stages...");
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction88
                // Insert post-action code here
                } else if (command == stagesCancelCmd) {//GEN-LINE:MVDCACase88
                // Insert pre-action code here
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction92
                // Insert post-action code here
                } else if (command == stagesUncheckAllCmd) {//GEN-LINE:MVDCACase92
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction94
                // Insert post-action code here
                boolean[] selected = new boolean[listChooseStage.size()]; // false
                listChooseStage.setSelectedFlags(selected);
                }//GEN-BEGIN:MVDCACase94
            } else if (displayable == listTimes) {
                if (command == cancelCommand2) {//GEN-END:MVDCACase94
                // Insert pre-action code here
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction56
                // Insert post-action code here
                } else if (command == listTimesOkCmd) {//GEN-LINE:MVDCACase56
                // Insert pre-action code here
                DayAndTime slot=kBegin.clone();
                int sel = listTimes.getSelectedIndex();
                while (slot.compareTo(kEnd, Calendar.FRIDAY)<=0) {
                    if (sel==0) {
                        System.out.println("DEBUG: changing selected time from "+selectedTimeSlot.asShortString()+" to "+slot.asShortString());
                        selectedTimeSlot = slot;
                        selectedEvent = null;
                        break;
                    }
                    --sel;
                    slot.incHour(kBeginHour,kEndHour);
                }
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction54
                // Insert post-action code here
                } else if (command == timesSaturdayCmd) {//GEN-LINE:MVDCACase54
                // Insert pre-action code here
                selectedTimeSlot = new DayAndTime(Calendar.SATURDAY, selectedTimeSlot.hour, selectedTimeSlot.min);
                selectedEvent = null;
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction131
                // Insert post-action code here
                } else if (command == timesFridayCmd) {//GEN-LINE:MVDCACase131
                // Insert pre-action code here
                selectedTimeSlot = new DayAndTime(Calendar.FRIDAY, selectedTimeSlot.hour, selectedTimeSlot.min);
                selectedEvent = null;
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction129
                // Insert post-action code here
                } else if (command == timesSundayCmd) {//GEN-LINE:MVDCACase129
                // Insert pre-action code here
                selectedTimeSlot = new DayAndTime(Calendar.SUNDAY, selectedTimeSlot.hour, selectedTimeSlot.min);
                selectedEvent = null;
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction133
                // Insert post-action code here
                } else if (command == timesNowCmd) {//GEN-LINE:MVDCACase133
                // Insert pre-action code here
                Date now = new Date();
                if (now.getTime()<aclTime(Calendar.FRIDAY, kBeginHour,00).getTime())
                    selectedTimeSlot = kBegin.clone();
                else if (now.getTime()>aclTime(Calendar.SUNDAY, kEndHour, 00).getTime())
                    selectedTimeSlot = kEnd.clone();
                else
                    selectedTimeSlot = new DayAndTime(now);
                selectedEvent = null;
                this.fillList(events);
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction135
                // Insert post-action code here
                }//GEN-BEGIN:MVDCACase135
            } else if (displayable == helpAboutAlert) {
                if (command == backCommand1) {//GEN-END:MVDCACase135
                // Insert pre-action code here
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction102
                // Insert post-action code here
                }//GEN-BEGIN:MVDCACase102
            } else if (displayable == textBoxSearch) {
                if (command == okCommandSearch) {//GEN-END:MVDCACase102
                // Insert pre-action code here
                String searchStr = textBoxSearch.getString().trim().toLowerCase();
                if (searchStr.length()==0) {
                    getDisplay().setCurrent(get_list1());
                    return;
                }
                int lastFind = -1;
                int i=(lastFind==-1?0:lastFind+1);
                while (i<events.size()) {
                    ACLEvent e = (ACLEvent)events.get(i);
                    if (e.name().toLowerCase().indexOf(searchStr)!=-1) {
                        break;
                    }
                    ++i;
                }
                if (i==events.size()) {
                    getDisplay().setCurrent(new Alert("Search Failed","Did not find any events matching '"+searchStr+"'.", null, AlertType.ERROR), textBoxSearch);
                    return;
                }
                stagesFilter = null;
                showOnlyPicks = false;
                selectedTimeSlot = new DayAndTime(((ACLEvent)events.get(i)).start());
                selectedEvent = (ACLEvent)events.get(i);
                fillList(events);
                
                list1.removeCommand(listShowOnlyPicksCmd);
                listShowOnlyPicksCmd = new Command(showOnlyPicks?"Show All":"Only Picks", Command.SCREEN, 4);
                list1.addCommand(listShowOnlyPicksCmd);
                
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction116
                // Insert post-action code here
                
                } else if (command == cancelCommandSearch) {//GEN-LINE:MVDCACase116
                // Insert pre-action code here
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction118
                // Insert post-action code here
                }//GEN-BEGIN:MVDCACase118
            } else if (displayable == textBoxACLCode) {
                if (command == cancelCommandACLCode) {//GEN-END:MVDCACase118
                // Insert pre-action code here
                
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction125
                // Insert post-action code here
                } else if (command == okCommandACLCode) {//GEN-LINE:MVDCACase125
                // Insert pre-action code here
                String aclCodeStr = textBoxACLCode.getString().trim().toLowerCase();
                if (aclCodeStr.length()==0)
                    return;
                int aclCode=0;
                try {
                    aclCode = Integer.valueOf(aclCodeStr).intValue();
                } catch (NumberFormatException e) {
                    aclCode = 0;
                }
                if (aclCode<=0) {
                    getDisplay().setCurrent(new Alert("Invalid ACL Code","The ACL code you entered '"+aclCodeStr+"' is not a valid number.", null, AlertType.ERROR), textBoxACLCode);
                    return;
                }
                
                downloader.getStream("http://aclfestival.com/schedule/ftaf.aspx?sid=ACL"+aclCode, picksListener);
                //downloader.getStream("http://aclfestival.com/schedule/ftaf.aspx?sid=ACL"+aclCode, picksListener);
                
                getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction123
                // Insert post-action code here
                }//GEN-BEGIN:MVDCACase123
            } else if (displayable == helpAboutForm) {
                if (command == backCommand2) {//GEN-END:MVDCACase123
                // Insert pre-action code here
                    getDisplay().setCurrent(get_list1());//GEN-LINE:MVDCAAction155
                // Insert post-action code here
                } else if (command == visitSiteBlackwatchPlaidCmd) {//GEN-LINE:MVDCACase155
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction153
                // Insert post-action code here
                if (this.platformRequest("http://blackwatchplaid.com")) {
                    exitMIDlet();
                }
                } else if (command == donwloadUpdateCmd) {//GEN-LINE:MVDCACase153
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction158
                // Insert post-action code here
                if (this.platformRequest("http://blackwatchplaid.com/acl411.jad")) {
                    exitMIDlet();
                }
                } else if (command == resetCmd) {//GEN-LINE:MVDCACase158
                // Insert pre-action code here
                    // Do nothing//GEN-LINE:MVDCAAction160
                // Insert post-action code here
                String[] recordStores = RecordStore.listRecordStores();
                for (int i=0; recordStores!=null && i<recordStores.length; ++i) {
                    try {
                        System.out.println("DEBUG: reset about to delete recordStore '"+recordStores[i]+"'");
                        RecordStore.deleteRecordStore(recordStores[i]);
                    } catch (Exception e) {
                        System.out.println("ERROR: reset unexpected exception deleting recordStore '"+recordStores[i]+"': "+e);
                    }
                }
                System.out.println("ERROR: reset is exiting without saving");
                this.saveOnExit = false;
                this.exitMIDlet();
                }//GEN-BEGIN:MVDCACase160
            }//GEN-END:MVDCACase160
            // Insert global post-action code here
            if (displayable == list1) {
                if (command!=null && command == cmdLoadSchedule) {
                    // Insert pre-action code here
                    // Do nothing
                    // Insert post-action code here
//                    //downloader.getText("http://aclfestival.com/schedule/ftaf.aspx?sid=ACL246706", this);
//                    System.gc();
//                    downloader.getText("http://aclfestival.com/schedule/schedule_day1.aspx?loadcode=1", this);
                    
                }
            }
        } catch (Exception e) {
            System.out.println("ERROR: commandAction unexpected exception for command '"+command.getLabel()+"': "+e);
            e.printStackTrace();
            
        }
}//GEN-LINE:MVDCAEnd
    
    /**
     * This method should return an instance of the display.
     */
    public Display getDisplay() {//GEN-FIRST:MVDGetDisplay
        return Display.getDisplay(this);
    }//GEN-LAST:MVDGetDisplay
    
    /**
     * This method should exit the midlet.
     */
    public void exitMIDlet() {//GEN-FIRST:MVDExitMidlet
        getDisplay().setCurrent(null);
        destroyApp(true);
        notifyDestroyed();
    }//GEN-LAST:MVDExitMidlet
    
    
    
    /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin5
     * @return Instance for exitCommand component
     */
    public Command get_exitCommand() {
        if (exitCommand == null) {//GEN-END:MVDGetBegin5
            // Insert pre-init code here
            exitCommand = new Command("Exit", Command.EXIT, 9);//GEN-LINE:MVDGetInit5
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd5
        return exitCommand;
    }//GEN-END:MVDGetEnd5
    /** This method returns instance for simpleTableModel1 component and should be called instead of accessing simpleTableModel1 field directly.//GEN-BEGIN:MVDGetBegin7
     * @return Instance for simpleTableModel1 component
     */
    public org.netbeans.microedition.lcdui.SimpleTableModel get_simpleTableModel1() {
        if (simpleTableModel1 == null) {//GEN-END:MVDGetBegin7
            // Insert pre-init code here
            simpleTableModel1 = new org.netbeans.microedition.lcdui.SimpleTableModel();//GEN-BEGIN:MVDGetInit7
            simpleTableModel1.setValues(new String[][] {
                new String[] {
                    "Gnarls Barkley",
                    "test2",
                    "test3",
                },
                new String[] {
                    null,
                    null,
                    null,
                },
                new String[] {
                    null,
                    null,
                    null,
                },
            });
            simpleTableModel1.setColumnNames(new String[] {
                "stage1",
                "stage2",
                "stage3",
            });//GEN-END:MVDGetInit7
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd7
        return simpleTableModel1;
    }//GEN-END:MVDGetEnd7
    
    
    /** This method returns instance for cmdLoadSchedule component and should be called instead of accessing cmdLoadSchedule field directly.//GEN-BEGIN:MVDGetBegin14
     * @return Instance for cmdLoadSchedule component
     */
    public Command get_cmdLoadSchedule() {
        if (cmdLoadSchedule == null) {//GEN-END:MVDGetBegin14
            // Insert pre-init code here
            cmdLoadSchedule = new Command("Load Schedule", Command.SCREEN, 1);//GEN-LINE:MVDGetInit14
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd14
        return cmdLoadSchedule;
    }//GEN-END:MVDGetEnd14
    
    /** This method returns instance for ticker1 component and should be called instead of accessing ticker1 field directly.//GEN-BEGIN:MVDGetBegin17
     * @return Instance for ticker1 component
     */
    public Ticker get_ticker1() {
        if (ticker1 == null) {//GEN-END:MVDGetBegin17
            // Insert pre-init code here
            ticker1 = new Ticker("<Enter Ticker Text>");//GEN-LINE:MVDGetInit17
            // Insert post-init code here
            ticker1.setString(kBuildVersion);
        }//GEN-BEGIN:MVDGetEnd17
        return ticker1;
    }//GEN-END:MVDGetEnd17
    
    /** This method returns instance for invalidateTableCmd component and should be called instead of accessing invalidateTableCmd field directly.//GEN-BEGIN:MVDGetBegin18
     * @return Instance for invalidateTableCmd component
     */
    public Command get_invalidateTableCmd() {
        if (invalidateTableCmd == null) {//GEN-END:MVDGetBegin18
            // Insert pre-init code here
            invalidateTableCmd = new Command("invalidateTable", Command.SCREEN, 3);//GEN-LINE:MVDGetInit18
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd18
        return invalidateTableCmd;
    }//GEN-END:MVDGetEnd18
    
    /** This method returns instance for list1 component and should be called instead of accessing list1 field directly.//GEN-BEGIN:MVDGetBegin20
     * @return Instance for list1 component
     */
    public List get_list1() {
        if (list1 == null) {//GEN-END:MVDGetBegin20
            // Insert pre-init code here
            list1 = new List("Schedule", Choice.IMPLICIT, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit20
            list1.addCommand(get_scheduleSearchCmd());
            list1.addCommand(get_pickEventCmd());
            list1.addCommand(get_timeCmd());
            list1.addCommand(get_stageFilterCmd());
            list1.addCommand(get_helpCommand1());
            list1.addCommand(get_exitCommand1());
            list1.addCommand(get_loadScheduleFromResourceCmd());
            list1.addCommand(get_listShowOnlyPicksCmd());
            list1.addCommand(get_scheduleLoadPicksCmd());
            list1.addCommand(get_dumpJSONCmd());
            list1.addCommand(get_cmdLoadSchedule());
            list1.setCommandListener(this);
            list1.setSelectedFlags(new boolean[0]);
            list1.setSelectCommand(get_pickEventCmd());
            list1.setFitPolicy(Choice.TEXT_WRAP_OFF);//GEN-END:MVDGetInit20
            // Insert post-init code here
            list1.removeCommand(get_scheduleLoadPicksCmd()); //!!! need to fix
            list1.removeCommand(get_dumpJSONCmd()); //!!! need to fix
            list1.removeCommand(get_loadScheduleFromResourceCmd()); //!!! need to fix
            //list1.addCommand(get_cmdLoadSchedule()); //!!! need to fix
            
        }//GEN-BEGIN:MVDGetEnd20
        return list1;
    }//GEN-END:MVDGetEnd20
    
    /** This method returns instance for itemCommand1 component and should be called instead of accessing itemCommand1 field directly.//GEN-BEGIN:MVDGetBegin30
     * @return Instance for itemCommand1 component
     */
    public Command get_itemCommand1() {
        if (itemCommand1 == null) {//GEN-END:MVDGetBegin30
            // Insert pre-init code here
            itemCommand1 = new Command("Show only...", Command.ITEM, 1);//GEN-LINE:MVDGetInit30
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd30
        return itemCommand1;
    }//GEN-END:MVDGetEnd30
    
    /** This method returns instance for stageFilterCmd component and should be called instead of accessing stageFilterCmd field directly.//GEN-BEGIN:MVDGetBegin32
     * @return Instance for stageFilterCmd component
     */
    public Command get_stageFilterCmd() {
        if (stageFilterCmd == null) {//GEN-END:MVDGetBegin32
            // Insert pre-init code here
            stageFilterCmd = new Command("Stages...", Command.SCREEN, 3);//GEN-LINE:MVDGetInit32
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd32
        return stageFilterCmd;
    }//GEN-END:MVDGetEnd32
    
    /** This method returns instance for listChooseStage component and should be called instead of accessing listChooseStage field directly.//GEN-BEGIN:MVDGetBegin34
     * @return Instance for listChooseStage component
     */
    public List get_listChooseStage() {
        if (listChooseStage == null) {//GEN-END:MVDGetBegin34
            // Insert pre-init code here
            listChooseStage = new List(null, Choice.MULTIPLE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit34
            listChooseStage.addCommand(get_okCommand1());
            listChooseStage.addCommand(get_stagesShowAllCmd());
            listChooseStage.addCommand(get_stagesCancelCmd());
            listChooseStage.addCommand(get_stagesUncheckAllCmd());
            listChooseStage.setCommandListener(this);
            listChooseStage.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit34
            // Insert post-init code here
            
        }//GEN-BEGIN:MVDGetEnd34
        return listChooseStage;
    }//GEN-END:MVDGetEnd34
    
    /** This method returns instance for okCommand1 component and should be called instead of accessing okCommand1 field directly.//GEN-BEGIN:MVDGetBegin36
     * @return Instance for okCommand1 component
     */
    public Command get_okCommand1() {
        if (okCommand1 == null) {//GEN-END:MVDGetBegin36
            // Insert pre-init code here
            okCommand1 = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit36
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd36
        return okCommand1;
    }//GEN-END:MVDGetEnd36
    
    /** This method returns instance for bpgMascotImg component and should be called instead of accessing bpgMascotImg field directly.//GEN-BEGIN:MVDGetBegin40
     * @return Instance for bpgMascotImg component
     */
    public Image get_bpgMascotImg() {
        if (bpgMascotImg == null) {//GEN-END:MVDGetBegin40
            // Insert pre-init code here
            try {//GEN-BEGIN:MVDGetInit40
                bpgMascotImg = Image.createImage("/com/blackwatchplaid/bpgfavanim.gif");
            } catch (java.io.IOException exception) {
            }//GEN-END:MVDGetInit40
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd40
        return bpgMascotImg;
    }//GEN-END:MVDGetEnd40
    
    /** This method returns instance for dumpJSONCmd component and should be called instead of accessing dumpJSONCmd field directly.//GEN-BEGIN:MVDGetBegin45
     * @return Instance for dumpJSONCmd component
     */
    public Command get_dumpJSONCmd() {
        if (dumpJSONCmd == null) {//GEN-END:MVDGetBegin45
            // Insert pre-init code here
            dumpJSONCmd = new Command("Dump JSON", Command.SCREEN, 5);//GEN-LINE:MVDGetInit45
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd45
        return dumpJSONCmd;
    }//GEN-END:MVDGetEnd45
    
    /** This method returns instance for loadScheduleFromResourceCmd component and should be called instead of accessing loadScheduleFromResourceCmd field directly.//GEN-BEGIN:MVDGetBegin47
     * @return Instance for loadScheduleFromResourceCmd component
     */
    public Command get_loadScheduleFromResourceCmd() {
        if (loadScheduleFromResourceCmd == null) {//GEN-END:MVDGetBegin47
            // Insert pre-init code here
            loadScheduleFromResourceCmd = new Command("Load Static Schedule", Command.SCREEN, 6);//GEN-LINE:MVDGetInit47
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd47
        return loadScheduleFromResourceCmd;
    }//GEN-END:MVDGetEnd47
    
    /** This method returns instance for timeCmd component and should be called instead of accessing timeCmd field directly.//GEN-BEGIN:MVDGetBegin49
     * @return Instance for timeCmd component
     */
    public Command get_timeCmd() {
        if (timeCmd == null) {//GEN-END:MVDGetBegin49
            // Insert pre-init code here
            timeCmd = new Command("Go to time...", Command.SCREEN, 2);//GEN-LINE:MVDGetInit49
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd49
        return timeCmd;
    }//GEN-END:MVDGetEnd49
    
    /** This method returns instance for listTimesOkCmd component and should be called instead of accessing listTimesOkCmd field directly.//GEN-BEGIN:MVDGetBegin53
     * @return Instance for listTimesOkCmd component
     */
    public Command get_listTimesOkCmd() {
        if (listTimesOkCmd == null) {//GEN-END:MVDGetBegin53
            // Insert pre-init code here
            listTimesOkCmd = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit53
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd53
        return listTimesOkCmd;
    }//GEN-END:MVDGetEnd53
    
    /** This method returns instance for cancelCommand2 component and should be called instead of accessing cancelCommand2 field directly.//GEN-BEGIN:MVDGetBegin55
     * @return Instance for cancelCommand2 component
     */
    public Command get_cancelCommand2() {
        if (cancelCommand2 == null) {//GEN-END:MVDGetBegin55
            // Insert pre-init code here
            cancelCommand2 = new Command("Cancel", Command.BACK, 2);//GEN-LINE:MVDGetInit55
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd55
        return cancelCommand2;
    }//GEN-END:MVDGetEnd55
    
    /** This method returns instance for stagesShowAllCmd component and should be called instead of accessing stagesShowAllCmd field directly.//GEN-BEGIN:MVDGetBegin87
     * @return Instance for stagesShowAllCmd component
     */
    public Command get_stagesShowAllCmd() {
        if (stagesShowAllCmd == null) {//GEN-END:MVDGetBegin87
            // Insert pre-init code here
            stagesShowAllCmd = new Command(LocalizationSupport.getMessage("Show_All"), Command.SCREEN, 4);//GEN-LINE:MVDGetInit87
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd87
        return stagesShowAllCmd;
    }//GEN-END:MVDGetEnd87
    
    /** This method returns instance for stagesCancelCmd component and should be called instead of accessing stagesCancelCmd field directly.//GEN-BEGIN:MVDGetBegin91
     * @return Instance for stagesCancelCmd component
     */
    public Command get_stagesCancelCmd() {
        if (stagesCancelCmd == null) {//GEN-END:MVDGetBegin91
            // Insert pre-init code here
            stagesCancelCmd = new Command("Cancel", Command.BACK, 4);//GEN-LINE:MVDGetInit91
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd91
        return stagesCancelCmd;
    }//GEN-END:MVDGetEnd91
    
    /** This method returns instance for stagesUncheckAllCmd component and should be called instead of accessing stagesUncheckAllCmd field directly.//GEN-BEGIN:MVDGetBegin93
     * @return Instance for stagesUncheckAllCmd component
     */
    public Command get_stagesUncheckAllCmd() {
        if (stagesUncheckAllCmd == null) {//GEN-END:MVDGetBegin93
            // Insert pre-init code here
            stagesUncheckAllCmd = new Command("Uncheck All", Command.SCREEN, 3);//GEN-LINE:MVDGetInit93
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd93
        return stagesUncheckAllCmd;
    }//GEN-END:MVDGetEnd93
    
    /** This method returns instance for exitCommand1 component and should be called instead of accessing exitCommand1 field directly.//GEN-BEGIN:MVDGetBegin95
     * @return Instance for exitCommand1 component
     */
    public Command get_exitCommand1() {
        if (exitCommand1 == null) {//GEN-END:MVDGetBegin95
            // Insert pre-init code here
            exitCommand1 = new Command("Exit", Command.EXIT, 8);//GEN-LINE:MVDGetInit95
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd95
        return exitCommand1;
    }//GEN-END:MVDGetEnd95
    
    /** This method returns instance for screenCommand1 component and should be called instead of accessing screenCommand1 field directly.//GEN-BEGIN:MVDGetBegin97
     * @return Instance for screenCommand1 component
     */
    public Command get_screenCommand1() {
        if (screenCommand1 == null) {//GEN-END:MVDGetBegin97
            // Insert pre-init code here
            screenCommand1 = new Command("Screen", Command.SCREEN, 1);//GEN-LINE:MVDGetInit97
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd97
        return screenCommand1;
    }//GEN-END:MVDGetEnd97
    
    /** This method returns instance for helpAboutAlert component and should be called instead of accessing helpAboutAlert field directly.//GEN-BEGIN:MVDGetBegin99
     * @return Instance for helpAboutAlert component
     */
    public Alert get_helpAboutAlert() {
        if (helpAboutAlert == null) {//GEN-END:MVDGetBegin99
            // Insert pre-init code here
            helpAboutAlert = new Alert("Help=>About", "ACL411 1.1 BETA\n2006-09-12\n\nHello. This is an Austin City Limits Festival schedule viewer. It is distributed by The Blackwatch Plaid Group <blackwatchplaidgroup@gmail.com>, which has no ties to Austin City Limits.\n\nSo you actually got this thing to run on your phone? Great. Make sure you download the latest vresion on Thursday, 2006-09-14 at\n\nhttp://blackwatchplaid.com\n\nThis software is distributed under the GNU Public License, so the source code is available.", get_bpgMascotImg(), AlertType.INFO);//GEN-BEGIN:MVDGetInit99
            helpAboutAlert.addCommand(get_backCommand1());
            helpAboutAlert.setCommandListener(this);
            helpAboutAlert.setTimeout(-2);//GEN-END:MVDGetInit99
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd99
        return helpAboutAlert;
    }//GEN-END:MVDGetEnd99
    
    /** This method returns instance for backCommand1 component and should be called instead of accessing backCommand1 field directly.//GEN-BEGIN:MVDGetBegin101
     * @return Instance for backCommand1 component
     */
    public Command get_backCommand1() {
        if (backCommand1 == null) {//GEN-END:MVDGetBegin101
            // Insert pre-init code here
            backCommand1 = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit101
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd101
        return backCommand1;
    }//GEN-END:MVDGetEnd101
    
    /** This method returns instance for helpCommand1 component and should be called instead of accessing helpCommand1 field directly.//GEN-BEGIN:MVDGetBegin105
     * @return Instance for helpCommand1 component
     */
    public Command get_helpCommand1() {
        if (helpCommand1 == null) {//GEN-END:MVDGetBegin105
            // Insert pre-init code here
            helpCommand1 = new Command("Help", Command.HELP, 7);//GEN-LINE:MVDGetInit105
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd105
        return helpCommand1;
    }//GEN-END:MVDGetEnd105
    
    /** This method returns instance for splashScreen1 component and should be called instead of accessing splashScreen1 field directly.//GEN-BEGIN:MVDGetBegin107
     * @return Instance for splashScreen1 component
     */
    public org.netbeans.microedition.lcdui.SplashScreen get_splashScreen1() {
        if (splashScreen1 == null) {//GEN-END:MVDGetBegin107
            // Insert pre-init code here
            splashScreen1 = new org.netbeans.microedition.lcdui.SplashScreen(getDisplay());//GEN-BEGIN:MVDGetInit107
            splashScreen1.setTitle("ACL 411");
            splashScreen1.setText("Loading schedule...");
            splashScreen1.setNextDisplayable(get_list1());
            splashScreen1.setTimeout(8000);//GEN-END:MVDGetInit107
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd107
        return splashScreen1;
    }//GEN-END:MVDGetEnd107
    
    /** This method returns instance for okCommand2 component and should be called instead of accessing okCommand2 field directly.//GEN-BEGIN:MVDGetBegin110
     * @return Instance for okCommand2 component
     */
    public Command get_okCommand2() {
        if (okCommand2 == null) {//GEN-END:MVDGetBegin110
            // Insert pre-init code here
            okCommand2 = new Command("Command", Command.OK, 1);//GEN-LINE:MVDGetInit110
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd110
        return okCommand2;
    }//GEN-END:MVDGetEnd110
    
    /** This method returns instance for textBoxSearch component and should be called instead of accessing textBoxSearch field directly.//GEN-BEGIN:MVDGetBegin114
     * @return Instance for textBoxSearch component
     */
    public TextBox get_textBoxSearch() {
        if (textBoxSearch == null) {//GEN-END:MVDGetBegin114
            // Insert pre-init code here
            textBoxSearch = new TextBox("Enter event name", "", 120, TextField.ANY);//GEN-BEGIN:MVDGetInit114
            textBoxSearch.addCommand(get_okCommandSearch());
            textBoxSearch.addCommand(get_cancelCommandSearch());
            textBoxSearch.setCommandListener(this);
            textBoxSearch.setInitialInputMode("");//GEN-END:MVDGetInit114
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd114
        return textBoxSearch;
    }//GEN-END:MVDGetEnd114
    
    /** This method returns instance for okCommandSearch component and should be called instead of accessing okCommandSearch field directly.//GEN-BEGIN:MVDGetBegin115
     * @return Instance for okCommandSearch component
     */
    public Command get_okCommandSearch() {
        if (okCommandSearch == null) {//GEN-END:MVDGetBegin115
            // Insert pre-init code here
            okCommandSearch = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit115
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd115
        return okCommandSearch;
    }//GEN-END:MVDGetEnd115
    
    /** This method returns instance for cancelCommandSearch component and should be called instead of accessing cancelCommandSearch field directly.//GEN-BEGIN:MVDGetBegin117
     * @return Instance for cancelCommandSearch component
     */
    public Command get_cancelCommandSearch() {
        if (cancelCommandSearch == null) {//GEN-END:MVDGetBegin117
            // Insert pre-init code here
            cancelCommandSearch = new Command("Cancel", Command.CANCEL, 2);//GEN-LINE:MVDGetInit117
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd117
        return cancelCommandSearch;
    }//GEN-END:MVDGetEnd117
    
    /** This method returns instance for scheduleLoadPicksCmd component and should be called instead of accessing scheduleLoadPicksCmd field directly.//GEN-BEGIN:MVDGetBegin119
     * @return Instance for scheduleLoadPicksCmd component
     */
    public Command get_scheduleLoadPicksCmd() {
        if (scheduleLoadPicksCmd == null) {//GEN-END:MVDGetBegin119
            // Insert pre-init code here
            scheduleLoadPicksCmd = new Command("Load ACL picks", Command.SCREEN, 4);//GEN-LINE:MVDGetInit119
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd119
        return scheduleLoadPicksCmd;
    }//GEN-END:MVDGetEnd119
    
    /** This method returns instance for textBoxACLCode component and should be called instead of accessing textBoxACLCode field directly.//GEN-BEGIN:MVDGetBegin121
     * @return Instance for textBoxACLCode component
     */
    public TextBox get_textBoxACLCode() {
        if (textBoxACLCode == null) {//GEN-END:MVDGetBegin121
            // Insert pre-init code here
            textBoxACLCode = new TextBox("Enter an ACL Code (number only)", "246706", 10, TextField.NUMERIC);//GEN-BEGIN:MVDGetInit121
            textBoxACLCode.addCommand(get_okCommandACLCode());
            textBoxACLCode.addCommand(get_cancelCommandACLCode());
            textBoxACLCode.setCommandListener(this);//GEN-END:MVDGetInit121
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd121
        return textBoxACLCode;
    }//GEN-END:MVDGetEnd121
    
    /** This method returns instance for okCommandACLCode component and should be called instead of accessing okCommandACLCode field directly.//GEN-BEGIN:MVDGetBegin122
     * @return Instance for okCommandACLCode component
     */
    public Command get_okCommandACLCode() {
        if (okCommandACLCode == null) {//GEN-END:MVDGetBegin122
            // Insert pre-init code here
            okCommandACLCode = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit122
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd122
        return okCommandACLCode;
    }//GEN-END:MVDGetEnd122
    
    /** This method returns instance for cancelCommandACLCode component and should be called instead of accessing cancelCommandACLCode field directly.//GEN-BEGIN:MVDGetBegin124
     * @return Instance for cancelCommandACLCode component
     */
    public Command get_cancelCommandACLCode() {
        if (cancelCommandACLCode == null) {//GEN-END:MVDGetBegin124
            // Insert pre-init code here
            cancelCommandACLCode = new Command("Cancel", Command.CANCEL, 2);//GEN-LINE:MVDGetInit124
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd124
        return cancelCommandACLCode;
    }//GEN-END:MVDGetEnd124
    /** This method returns instance for timesFridayCmd component and should be called instead of accessing timesFridayCmd field directly.//GEN-BEGIN:MVDGetBegin128
     * @return Instance for timesFridayCmd component
     */
    public Command get_timesFridayCmd() {
        if (timesFridayCmd == null) {//GEN-END:MVDGetBegin128
            // Insert pre-init code here
            timesFridayCmd = new Command("Friday", Command.SCREEN, 3);//GEN-LINE:MVDGetInit128
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd128
        return timesFridayCmd;
    }//GEN-END:MVDGetEnd128
    
    /** This method returns instance for timesSaturdayCmd component and should be called instead of accessing timesSaturdayCmd field directly.//GEN-BEGIN:MVDGetBegin130
     * @return Instance for timesSaturdayCmd component
     */
    public Command get_timesSaturdayCmd() {
        if (timesSaturdayCmd == null) {//GEN-END:MVDGetBegin130
            // Insert pre-init code here
            timesSaturdayCmd = new Command("Saturday", Command.SCREEN, 4);//GEN-LINE:MVDGetInit130
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd130
        return timesSaturdayCmd;
    }//GEN-END:MVDGetEnd130
    
    /** This method returns instance for timesSundayCmd component and should be called instead of accessing timesSundayCmd field directly.//GEN-BEGIN:MVDGetBegin132
     * @return Instance for timesSundayCmd component
     */
    public Command get_timesSundayCmd() {
        if (timesSundayCmd == null) {//GEN-END:MVDGetBegin132
            // Insert pre-init code here
            timesSundayCmd = new Command("Sunday", Command.SCREEN, 5);//GEN-LINE:MVDGetInit132
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd132
        return timesSundayCmd;
    }//GEN-END:MVDGetEnd132
    
    /** This method returns instance for listTimes component and should be called instead of accessing listTimes field directly.//GEN-BEGIN:MVDGetBegin51
     * @return Instance for listTimes component
     */
    public List get_listTimes() {
        if (listTimes == null) {//GEN-END:MVDGetBegin51
            // Insert pre-init code here
            listTimes = new List("Go to hour / day...", Choice.IMPLICIT, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit51
            listTimes.addCommand(get_listTimesOkCmd());
            listTimes.addCommand(get_cancelCommand2());
            listTimes.addCommand(get_timesNowCmd());
            listTimes.addCommand(get_timesFridayCmd());
            listTimes.addCommand(get_timesSaturdayCmd());
            listTimes.addCommand(get_timesSundayCmd());
            listTimes.setCommandListener(this);
            listTimes.setSelectedFlags(new boolean[0]);
            listTimes.setSelectCommand(get_listTimesOkCmd());//GEN-END:MVDGetInit51
            // Insert post-init code here
            listTimes.deleteAll();
            for (DayAndTime slot=kBegin.clone(); slot.compareTo(kEnd, Calendar.FRIDAY)<=0; slot.incHour(kBeginHour,kEndHour)) {
                listTimes.append(slot.asShortString(),null);
            }
        }//GEN-BEGIN:MVDGetEnd51
        return listTimes;
    }//GEN-END:MVDGetEnd51
    
    /** This method returns instance for scheduleSearchCmd component and should be called instead of accessing scheduleSearchCmd field directly.//GEN-BEGIN:MVDGetBegin112
     * @return Instance for scheduleSearchCmd component
     */
    public Command get_scheduleSearchCmd() {
        if (scheduleSearchCmd == null) {//GEN-END:MVDGetBegin112
            // Insert pre-init code here
            scheduleSearchCmd = new Command("Search", Command.SCREEN, 1);//GEN-LINE:MVDGetInit112
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd112
        return scheduleSearchCmd;
    }//GEN-END:MVDGetEnd112
    
    /** This method returns instance for timesNowCmd component and should be called instead of accessing timesNowCmd field directly.//GEN-BEGIN:MVDGetBegin134
     * @return Instance for timesNowCmd component
     */
    public Command get_timesNowCmd() {
        if (timesNowCmd == null) {//GEN-END:MVDGetBegin134
            // Insert pre-init code here
            timesNowCmd = new Command("Now", Command.SCREEN, 3);//GEN-LINE:MVDGetInit134
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd134
        return timesNowCmd;
    }//GEN-END:MVDGetEnd134
    
    /** This method returns instance for listShowOnlyPicksCmd component and should be called instead of accessing listShowOnlyPicksCmd field directly.//GEN-BEGIN:MVDGetBegin136
     * @return Instance for listShowOnlyPicksCmd component
     */
    public Command get_listShowOnlyPicksCmd() {
        if (listShowOnlyPicksCmd == null) {//GEN-END:MVDGetBegin136
            // Insert pre-init code here
            listShowOnlyPicksCmd = new Command("Only Picks", Command.SCREEN, 3);//GEN-LINE:MVDGetInit136
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd136
        return listShowOnlyPicksCmd;
    }//GEN-END:MVDGetEnd136
    
    /** This method returns instance for listPickSources component and should be called instead of accessing listPickSources field directly.//GEN-BEGIN:MVDGetBegin138
     * @return Instance for listPickSources component
     */
    public List get_listPickSources() {
        if (listPickSources == null) {//GEN-END:MVDGetBegin138
            // Insert pre-init code here
            listPickSources = new List("Show these picks", Choice.MULTIPLE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit138
            listPickSources.setCommandListener(this);
            listPickSources.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit138
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd138
        return listPickSources;
    }//GEN-END:MVDGetEnd138
    
    /** This method returns instance for setAsPrimaryPickCmd component and should be called instead of accessing setAsPrimaryPickCmd field directly.//GEN-BEGIN:MVDGetBegin140
     * @return Instance for setAsPrimaryPickCmd component
     */
    public Command get_setAsPrimaryPickCmd() {
        if (setAsPrimaryPickCmd == null) {//GEN-END:MVDGetBegin140
            // Insert pre-init code here
            setAsPrimaryPickCmd = new Command("Item", Command.ITEM, 1);//GEN-LINE:MVDGetInit140
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd140
        return setAsPrimaryPickCmd;
    }//GEN-END:MVDGetEnd140
    
    /** This method returns instance for pickEventCmd component and should be called instead of accessing pickEventCmd field directly.//GEN-BEGIN:MVDGetBegin142
     * @return Instance for pickEventCmd component
     */
    public Command get_pickEventCmd() {
        if (pickEventCmd == null) {//GEN-END:MVDGetBegin142
            // Insert pre-init code here
            pickEventCmd = new Command("Pick", Command.ITEM, 3);//GEN-LINE:MVDGetInit142
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd142
        return pickEventCmd;
    }//GEN-END:MVDGetEnd142
    
    /** This method returns instance for helpAboutForm component and should be called instead of accessing helpAboutForm field directly.//GEN-BEGIN:MVDGetBegin146
     * @return Instance for helpAboutForm component
     */
    public Form get_helpAboutForm() {
        if (helpAboutForm == null) {//GEN-END:MVDGetBegin146
            // Insert pre-init code here
            helpAboutForm = new Form("Help=>About", new Item[] {//GEN-BEGIN:MVDGetInit146
                get_imageItem1(),
                get_stringItem1(),
                get_stringItem2(),
                get_stringItem3()
            });
            helpAboutForm.addCommand(get_visitSiteBlackwatchPlaidCmd());
            helpAboutForm.addCommand(get_backCommand2());
            helpAboutForm.addCommand(get_donwloadUpdateCmd());
            helpAboutForm.addCommand(get_resetCmd());
            helpAboutForm.setCommandListener(this);//GEN-END:MVDGetInit146
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd146
        return helpAboutForm;
    }//GEN-END:MVDGetEnd146
    
    /** This method returns instance for imageItem1 component and should be called instead of accessing imageItem1 field directly.//GEN-BEGIN:MVDGetBegin147
     * @return Instance for imageItem1 component
     */
    public ImageItem get_imageItem1() {
        if (imageItem1 == null) {//GEN-END:MVDGetBegin147
            // Insert pre-init code here
            imageItem1 = new ImageItem("", get_bpgMascotImg(), ImageItem.LAYOUT_LEFT | Item.LAYOUT_VCENTER | Item.LAYOUT_SHRINK, "");//GEN-LINE:MVDGetInit147
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd147
        return imageItem1;
    }//GEN-END:MVDGetEnd147
    
    /** This method returns instance for visitSiteBlackwatchPlaidCmd component and should be called instead of accessing visitSiteBlackwatchPlaidCmd field directly.//GEN-BEGIN:MVDGetBegin152
     * @return Instance for visitSiteBlackwatchPlaidCmd component
     */
    public Command get_visitSiteBlackwatchPlaidCmd() {
        if (visitSiteBlackwatchPlaidCmd == null) {//GEN-END:MVDGetBegin152
            // Insert pre-init code here
            visitSiteBlackwatchPlaidCmd = new Command("Website", Command.SCREEN, 2);//GEN-LINE:MVDGetInit152
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd152
        return visitSiteBlackwatchPlaidCmd;
    }//GEN-END:MVDGetEnd152
    
    /** This method returns instance for backCommand2 component and should be called instead of accessing backCommand2 field directly.//GEN-BEGIN:MVDGetBegin154
     * @return Instance for backCommand2 component
     */
    public Command get_backCommand2() {
        if (backCommand2 == null) {//GEN-END:MVDGetBegin154
            // Insert pre-init code here
            backCommand2 = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit154
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd154
        return backCommand2;
    }//GEN-END:MVDGetEnd154
    /** This method returns instance for donwloadUpdateCmd component and should be called instead of accessing donwloadUpdateCmd field directly.//GEN-BEGIN:MVDGetBegin157
     * @return Instance for donwloadUpdateCmd component
     */
    public Command get_donwloadUpdateCmd() {
        if (donwloadUpdateCmd == null) {//GEN-END:MVDGetBegin157
            // Insert pre-init code here
            donwloadUpdateCmd = new Command("Download Update", Command.SCREEN, 2);//GEN-LINE:MVDGetInit157
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd157
        return donwloadUpdateCmd;
    }//GEN-END:MVDGetEnd157
    
    /** This method returns instance for resetCmd component and should be called instead of accessing resetCmd field directly.//GEN-BEGIN:MVDGetBegin159
     * @return Instance for resetCmd component
     */
    public Command get_resetCmd() {
        if (resetCmd == null) {//GEN-END:MVDGetBegin159
            // Insert pre-init code here
            resetCmd = new Command("Reset!!! & Exit", Command.SCREEN, 4);//GEN-LINE:MVDGetInit159
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd159
        return resetCmd;
    }//GEN-END:MVDGetEnd159
    
    /** This method returns instance for textField2 component and should be called instead of accessing textField2 field directly.//GEN-BEGIN:MVDGetBegin161
     * @return Instance for textField2 component
     */
    public TextField get_textField2() {
        if (textField2 == null) {//GEN-END:MVDGetBegin161
            // Insert pre-init code here
            textField2 = new TextField("textField2", null, 120, TextField.ANY);//GEN-BEGIN:MVDGetInit161
            textField2.setLayout(Item.LAYOUT_RIGHT);//GEN-END:MVDGetInit161
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd161
        return textField2;
    }//GEN-END:MVDGetEnd161
    
    
    /** This method returns instance for stringItem1 component and should be called instead of accessing stringItem1 field directly.//GEN-BEGIN:MVDGetBegin163
     * @return Instance for stringItem1 component
     */
    public StringItem get_stringItem1() {
        if (stringItem1 == null) {//GEN-END:MVDGetBegin163
            // Insert pre-init code here
            stringItem1 = new StringItem("", LocalizationSupport.getMessage("BUILD_VERSION"));//GEN-BEGIN:MVDGetInit163
            stringItem1.setLayout(Item.LAYOUT_RIGHT | Item.LAYOUT_VCENTER | Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_SHRINK);//GEN-END:MVDGetInit163
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd163
        return stringItem1;
    }//GEN-END:MVDGetEnd163
    
    /** This method returns instance for stringItem2 component and should be called instead of accessing stringItem2 field directly.//GEN-BEGIN:MVDGetBegin164
     * @return Instance for stringItem2 component
     */
    public StringItem get_stringItem2() {
        if (stringItem2 == null) {//GEN-END:MVDGetBegin164
            // Insert pre-init code here
            stringItem2 = new StringItem("", LocalizationSupport.getMessage("HELP_ABOUT"));//GEN-LINE:MVDGetInit164
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd164
        return stringItem2;
    }//GEN-END:MVDGetEnd164

    /** This method returns instance for stringItem3 component and should be called instead of accessing stringItem3 field directly.//GEN-BEGIN:MVDGetBegin165
     * @return Instance for stringItem3 component
     */
    public StringItem get_stringItem3() {
        if (stringItem3 == null) {//GEN-END:MVDGetBegin165
            // Insert pre-init code here
            stringItem3 = new StringItem("", "blackwatchplaidGROUP@\ngmail.com\nhttp://blackwatchplaid.com\nCopyright 2006 All right");//GEN-BEGIN:MVDGetInit165
            stringItem3.setLayout(Item.LAYOUT_RIGHT);//GEN-END:MVDGetInit165
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd165
        return stringItem3;
    }//GEN-END:MVDGetEnd165
    
    public void startApp() {
        initialize();
    }
    
    public void pauseApp() {
        save();
    }
    
    public void destroyApp(boolean unconditional) {
        save();
        this.saveOnExit = true; // S710 emulator doesn't clear'

    }
    
    // Just an untested hack for Sony S710
    static public class AustinTimeZone2006 extends TimeZone {
        static TimeZone cst;
        static {
            cst = new AustinTimeZone2006();
        }
        public static TimeZone getInstance() {
            return cst;
        }
        
        public String 	getID() {
            return "America/Austin"; // should be Chicago
        }
        
        public boolean useDaylightTime() {
            return true;
        }
        public int getRawOffset() {
            return -6*60*60*1000;
        }
        // Compare dates easily to minute resolution
        private static int dateToInt(int month/*Jan=0*/, int day/*1-31*/, int millis) {
            // 11 25 1440
            return month*100*10000+day*10000+millis/1000/60; // April 2 2am
        }
        static final int kDSTBegin = dateToInt(3,2,2); // April 2 2am
        static final int kDSTEnd = dateToInt(9,29,2); // Oct 29 2am
        public int getOffset(int era, int year, int month, int day, int dayOfWeek, int millis) {
            /*months zero based*/
            int d=dateToInt(month,day,millis);
            return d>=kDSTBegin && d<kDSTEnd?-5*60*60*1000:-6*60*60*1000;
        }
        
    }
    static public class DayAndTime {
        int dayOfWeek;
        int hour;
        int min;
        DayAndTime(int dayOfWeekX, int hourOfDayX/*24*/, int minX) {
            this.dayOfWeek = dayOfWeekX;
            this.hour = hourOfDayX;
            this.min = min;
        }
        DayAndTime(Date d) {
            TimeZone cdt = TimeZone.getTimeZone("USCST");
//            if (cdt==null || cdt.getRawOffset()==0)
//                System.out.println("ERROR: Could not get central time zone.");
//            System.out.println("!!!DEBUG: getTimeZone(CST)="+cdt.getID()+" "+(cdt.getRawOffset()/1000/60/60)            +" SepOffest="+(cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60)+" DST="+cdt.useDaylightTime());
//            cdt = TimeZone.getDefault();
//            System.out.println("DEBUG: getTimeZone(CST)="+cdt.getID()+" rawoffset="+(cdt.getRawOffset()/1000/60/60)+" SepOffest="+(cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60)+" DST="+cdt.useDaylightTime());
            if (cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60 != 5) {
//                System.out.println("ERROR: Overriding default timezone getTimeZone(CDT)="+cdt.getID()+" rawoffset="+(cdt.getRawOffset()/1000/60/60)+" SepOffest="+(cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60)+" DST="+cdt.useDaylightTime());
                cdt=AustinTimeZone2006.getInstance();
            }
//            System.out.println("!!!DEBUG: getTimeZone(CST)="+cdt.getID()+" rawoffset="+(cdt.getRawOffset()/1000/60/60)+" SepOffest="+(cdt.getOffset(1,2006,9-1,15,6,0001)/1000/60/60)+" DST="+cdt.useDaylightTime()+" MarOffest="+(cdt.getOffset(1,2006,3-1,15,6,0001)/1000/60/60));
            Calendar cal = Calendar.getInstance(cdt);
            cal.setTime(d);
            dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
            hour = cal.get(Calendar.HOUR_OF_DAY);
            min = cal.get(Calendar.MINUTE);
        }
        
        DayAndTime clone() {
            return new DayAndTime(dayOfWeek,hour,min);
        }
        
        // Increment the hour, wrapping to next day at beginHour if it is after endHour
        // FRIDAY 17:00 incHour(11,17) => SATURDAY 11:00
        public void incHour(int beginHour, int endHour) {
            if (this.hour<endHour) {
                ++this.hour;
            } else {
                this.hour = beginHour;
                if (this.dayOfWeek==Calendar.SATURDAY) {
                    this.dayOfWeek = Calendar.SUNDAY;
                } else {
                    ++this.dayOfWeek;
                }
            }
        }
        
        static public int compare(int i1, int i2) {
            return i1-i2;
        }
        
        public int adjustedDayOfWeek(int startingDay) {
            return dayOfWeek>=startingDay ? dayOfWeek : dayOfWeek+7;
        }
        public int compareTo(DayAndTime other, int startingDay) {
            int r = adjustedDayOfWeek(startingDay)-other.adjustedDayOfWeek(startingDay);
            if (r!=0) return r;
            r = hour-other.hour;
            if (r!=0) return r;
            return min-other.min;
        }
        public int asMinutesSince(int startingDay) {
            return (dayOfWeek-Calendar.SUNDAY)*24*60 + hour*60 + min;
        }
        public String asTimeShortString() {
            return (hour<=12?hour:hour-12)+":"+(min<10?"0":"")+min+(hour<12?"a":"p");
        }
        static String[] kDayOfWeekShortStr = { "Notday", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
        static String[] kDayOfWeekStr = { "Notday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        public String asShortString() {
            return kDayOfWeekShortStr[dayOfWeek]+" "+(hour<=12?hour:hour-12)+":"+(min<10?"0":"")+min+(hour<12?"a":"p");
        }
        public String dayOfWeekStr() {
            return kDayOfWeekStr[dayOfWeek];
        }
        public String dayOfWeekShortStr() {
            return kDayOfWeekShortStr[dayOfWeek];
        }
    }
    
    public static Date aclTime(int dayOfWeek, int hour, int min) {
        //!!!Calendar cal = Calendar.getInstance(/*!!!TimeZone.getTimeZone("CDT")*/);
        Calendar cal = Calendar.getInstance(AustinTimeZone2006.getInstance());
        cal.set(Calendar.YEAR, 2006);
        cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
        cal.set(Calendar.DAY_OF_MONTH, dayOfWeek==Calendar.FRIDAY?15:(dayOfWeek==Calendar.SATURDAY?16:17));
        cal.set(Calendar.AM_PM, hour<=12?Calendar.AM:Calendar.PM);
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, min);
        return cal.getTime();
    }
}
